package com.gzz.orchid.common.boot.mybatis.utils;

import jakarta.annotation.Resource;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.util.List;
import java.util.function.BiFunction;
import java.util.function.ToIntBiFunction;

/**
 * @author higmd
 * 调用方法
 * batchUtils.batchUpdateOrInsert(数据集合, mapper.class, item -> mapper实例对象.insert方法(item));
 */
public class MybatisBatchUtils {
/**
        * 每次处理1000条
*/
    private static final int BATCH_SIZE = 1000;
    @Resource
    private SqlSessionFactory sqlSessionFactory;
    /**
     * 批量处理修改或者插入
     *
     * @param data 需要被处理的数据
     * @param mapperClass Mybatis的Mapper类
     * @param function 自定义处理逻辑
     * @return int 影响的总行数
     */
    public <T,U,R> int batchUpdateOrInsert(List<T> data, Class<U> mapperClass, BiFunction<T,U,R> function) {
        int i = 1;
        SqlSession batchSqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
        try {
            U mapper = batchSqlSession.getMapper(mapperClass);
            int size = data.size();
            for (T element : data) {
                function.apply(element,mapper);
                if ((i % BATCH_SIZE == 0) || i == size) {
                    batchSqlSession.flushStatements();
                    // batchSqlSession.commit();
                    // batchSqlSession.clearCache();
                }
                i++;
            }
            // 非事务环境下强制commit，事务情况下该commit相当于无效
            batchSqlSession.commit(!TransactionSynchronizationManager.isSynchronizationActive());
        } catch (Exception e) {
            batchSqlSession.rollback();
            throw new IllegalArgumentException(e);
        } finally {
            batchSqlSession.close();
        }
        return i - 1;
    }
   /**
    *
    * @param data 数据
    * @param mapperClass mapper的Class
    * @param sqlFunction 函数（具体的插入语句）
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public <T,U> int batchInsertOrUpdate(List<T> data, Class<U> mapperClass, ToIntBiFunction<T, U> sqlFunction){
        //SqlSessionFactory sqlSessionFactory = sqlSessionTemplate.getSqlSessionFactory();
        SqlSession batchSqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
        int count = 0;
        try {
            //使用新的mapper代理
            U mapper = (U) batchSqlSession.getMapper(mapperClass);
            for (int i = 0; i < data.size(); i++) {
                count += sqlFunction.applyAsInt(data.get(i), mapper);
                if (i != 0 && i % BATCH_SIZE == 0){
                    //刷新缓存，执行sql
                    batchSqlSession.flushStatements();
                }
            }
            batchSqlSession.flushStatements();
        } catch (Exception e) {
            throw new RuntimeException("批量处理发生问题"+e.getMessage());
        }
        return count;
    }
}
